package com.acme.bankapp.service.bank;

import com.acme.bankapp.domain.bank.account.*;
import com.acme.bankapp.domain.bank.client.*;
import com.acme.bankapp.exception.bank.*;

import java.io.*;
import java.util.Locale;
import java.util.Scanner;
import java.util.StringTokenizer;

class BankService {

    public static void addClient(Bank bank, Client client) throws BankException {

        int length = bank.clients.length;

        for (int i = 0; i < length; i++) {

            if (bank.clients[i] != null && bank.clients[i].fio.equals(client.fio)) {
                throw new ClientExistsException("ClientExistsException\n");
            }

            if (bank.clients[i] == null) {
                bank.clients[i] = client;
                for (int k = 0; k < bank.listener.length; k++) {
                    bank.listener[k].onClientAdded(client);
                }
                return;
            }

        }
        throw new BankException("BankException\n");

    }

    public static void saveBank(Bank bank, String path) throws Exception {
        if (bank == null || path == "") {
            throw new Exception("Invalid arguments!");
        }
        String[] list = new String[bank.clients.length];
        int i = 0;
        for (Client client : bank.clients) {
            if (client == null) {
                break;
            }
            CheckingAccount checkingAccount = client.checkingAccount;
            SavingAccount savingAccount = client.savingAccount;
            if (savingAccount != null && checkingAccount != null) {
                list[i] = String.format(Locale.ENGLISH, "accounttype=c&s;savBalance=%.2f;checkBalance=%.2f;overdraft=%.2f;",
                        savingAccount.getBalance(), checkingAccount.getBalance(), checkingAccount.getOverdraft());
            } else {
                if (savingAccount != null) {
                    list[i] = String.format(Locale.ENGLISH, "accounttype=s;savBalance=%.2f;",
                            savingAccount.getBalance());
                } else if (checkingAccount != null) {
                    list[i] = String.format(Locale.ENGLISH, "accounttype=c;checkBalance=%.2f;overdraft=%.2f;",
                            checkingAccount.getBalance(), checkingAccount.getOverdraft());
                }
            }
            list[i] += String.format("fio=%s;gender=%s%n", client.fio, client.gender);
            i++;
        }

        try (FileWriter fw = new FileWriter(path)) {
            for (String record : list) {
                if (record == null) {
                    break;
                }
                fw.write(record);
            }
            fw.flush();
        } catch (IOException e) {
            System.out.printf("%s", e);
        }
    }

    public static void readBank(Bank bank, String path) throws Exception {
        if (path == "" || bank == null) {
            throw new Exception("Invalid arguments!");
        }

        FileReader fr = new FileReader(path);
        String  s = "",   //for reading strings from file
                key = "",
                value = "",
                fio = "";
        int     flag = 0,
                i = 0;
        Gender gender = Gender.Male;

        StringTokenizer stoken_1, // for first tokens
                        stoken_2; // for second
        double
                savAccountBalance = 0.0,
                checkAccountBalance = 0.0,
                checkAccountOverdraft = 0.0;

        try (BufferedReader br = new BufferedReader(fr)) {
        while ((s = br.readLine()) != null) {
            stoken_1 = new StringTokenizer(s, ";");
            while (stoken_1.hasMoreTokens()) {
                stoken_2 = new StringTokenizer(stoken_1.nextToken(), "=");
                key = stoken_2.nextToken();
                value = stoken_2.nextToken();
                switch (key) {
                    case "accounttype":
                        switch (value) {
                            case "s":
                                flag = 1;
                                break;
                            case "c":
                                flag = 2;
                                break;
                            case "c&s":
                                flag = 3;
                                break;
                        }
                        break;
                    case "savBalance":
                        savAccountBalance = Double.parseDouble(value);
                        break;
                    case "checkBalance":
                        checkAccountBalance = Double.parseDouble(value);
                        break;
                    case "overdraft":
                        checkAccountOverdraft = Double.parseDouble(value);
                        break;
                    case "fio":
                        fio = value;
                        break;
                    case "gender":
                        gender = Gender.valueOf(value);
                        break;
                }
            }
            switch (flag) {
                case 1:
                    bank.clients[i++] = new Client(fio, gender, savAccountBalance);
                    break;
                case 2:
                    bank.clients[i++] = new Client(fio, gender, checkAccountBalance, checkAccountOverdraft);
                    break;
                case 3:
                    bank.clients[i++] = new Client(fio, gender, savAccountBalance, checkAccountBalance, checkAccountOverdraft);
                    break;
            }

        }
        } catch (Exception e) {
            System.out.printf("Error for reading file: %s\n", e.getMessage());
        }


    }


    public static void printMaximumAmountToWithdraw(Bank bank) {

        int length = bank.clients.length;

        for (int i = 0; i < length; i++) {
            if (bank.clients[i] == null) {
                break;
            }

            System.out.printf("Client %s \n", bank.clients[i].getClientSalutation());

            if (bank.clients[i].savingAccount != null) {
                System.out.printf("balance: %.2f\n", bank.clients[i].savingAccount.getBalance());
            }
            if (bank.clients[i].checkingAccount != null) {
                System.out.printf("balance with overdraft: %.2f\n", bank.clients[i].checkingAccount.maximumAmountToWithdraw());
            }


        }
    }

}